package org.refresh.core.conf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.refresh.core.Constraint;
import org.refresh.core.RefreshCore;
import org.refresh.core.expr.BinaryExpression;
import org.refresh.core.expr.Cardinality;
import org.refresh.core.expr.Expression;

/*******************************************************************************
 * Copyright (c) 2005 Jules White. All rights reserved. This program and the
 * accompanying materials are made available under the terms of the Common
 * Public License v1.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: Jules White - initial API and implementation
 ******************************************************************************/
public class RefreshProblem {

	private List sourceItems_ = new ArrayList();

	private List targetItems_ = new ArrayList();

	private Map<Object, List> requiresMap_ = new HashMap<Object, List>();

	private Map<Object, List> excludesMap_ = new HashMap<Object, List>();

	private Map<Object, List> selectMap_ = new HashMap<Object, List>();

	private Map<Object, Cardinality> sourceMappedInstancesCountMap_ = new HashMap<Object, Cardinality>();

	private Map<Object, Cardinality> targetMappedInstancesCountMap_ = new HashMap<Object, Cardinality>();

	private Map<Object, List<Constraint>> sourceFeasibilityConstraintsMap_ = new HashMap<Object, List<Constraint>>();

	private Map<Object, List> feasibleTargetsMap_ = new HashMap<Object, List>();

	private Map<Object,Map<Object, Integer>> sourceVariableValuesTable_ = new HashMap<Object,Map<Object, Integer>>();
	
	private Map<Object,Map<String, Object>> injectionValues_ = new HashMap<Object,Map<String, Object>>();
	
	private Expression goalFunction_;
	
	private boolean maximizeGoal_;
	/**
	 * @return the excludesMap
	 */
	public Map<Object, List> getExcludesMap() {
		return excludesMap_;
	}

	/**
	 * @param excludesMap
	 *            the excludesMap to set
	 */
	public void setExcludesMap(Map<Object, List> excludesMap) {
		excludesMap_ = excludesMap;
	}

	/**
	 * @return the feasibleTargetsMap
	 */
	public Map<Object, List> getFeasibleTargetsMap() {
		return feasibleTargetsMap_;
	}

	/**
	 * @param feasibleTargetsMap
	 *            the feasibleTargetsMap to set
	 */
	public void setFeasibleTargetsMap(Map<Object, List> feasibleTargetsMap) {
		feasibleTargetsMap_ = feasibleTargetsMap;
	}

	/**
	 * @return the requiresMap
	 */
	public Map<Object, List> getRequiresMap() {
		return requiresMap_;
	}

	/**
	 * @param requiresMap
	 *            the requiresMap to set
	 */
	public void setRequiresMap(Map<Object, List> requiresMap) {
		requiresMap_ = requiresMap;
	}

	/**
	 * @return the selectMap
	 */
	public Map<Object, List> getSelectMap() {
		return selectMap_;
	}

	/**
	 * @param selectMap
	 *            the selectMap to set
	 */
	public void setSelectMap(Map<Object, List> selectMap) {
		selectMap_ = selectMap;
	}

	/**
	 * @return the sourceFeasibilityConstraintsMap
	 */
	public Map<Object, List<Constraint>> getSourceFeasibilityConstraintsMap() {
		return sourceFeasibilityConstraintsMap_;
	}

	/**
	 * @param sourceFeasibilityConstraintsMap
	 *            the sourceFeasibilityConstraintsMap to set
	 */
	public void setSourceFeasibilityConstraintsMap(
			Map<Object, List<Constraint>> sourceFeasibilityConstraintsMap) {
		sourceFeasibilityConstraintsMap_ = sourceFeasibilityConstraintsMap;
	}

	/**
	 * @return the sourceItems
	 */
	public List getSourceItems() {
		return sourceItems_;
	}

	/**
	 * @param sourceItems
	 *            the sourceItems to set
	 */
	public void setSourceItems(List sourceItems) {
		sourceItems_ = sourceItems;
	}

	/**
	 * @return the sourceMappedInstancesCountMap
	 */
	public Map<Object, Cardinality> getSourceMappedInstancesCountMap() {
		return sourceMappedInstancesCountMap_;
	}

	/**
	 * @param sourceMappedInstancesCountMap
	 *            the sourceMappedInstancesCountMap to set
	 */
	public void setSourceMappedInstancesCountMap(
			Map<Object, Cardinality> sourceMappedInstancesCountMap) {
		sourceMappedInstancesCountMap_ = sourceMappedInstancesCountMap;
	}

	/**
	 * @return the targetItems
	 */
	public List getTargetItems() {
		return targetItems_;
	}

	/**
	 * @param targetItems
	 *            the targetItems to set
	 */
	public void setTargetItems(List targetItems) {
		targetItems_ = targetItems;
	}

	/**
	 * @return the targetMappedInstancesCountMap
	 */
	public Map<Object, Cardinality> getTargetMappedInstancesCountMap() {
		return targetMappedInstancesCountMap_;
	}

	/**
	 * @param targetMappedInstancesCountMap
	 *            the targetMappedInstancesCountMap to set
	 */
	public void setTargetMappedInstancesCountMap(
			Map<Object, Cardinality> targetMappedInstancesCountMap) {
		targetMappedInstancesCountMap_ = targetMappedInstancesCountMap;
	}
	
	

	/**
	 * @return the goalFunction
	 */
	public Expression getGoalFunction() {
		return goalFunction_;
	}

	/**
	 * @param goalFunction the goalFunction to set
	 */
	public void setGoalFunction(Expression goalFunction) {
		goalFunction_ = goalFunction;
	}

	/**
	 * @return the maximizeGoal
	 */
	public boolean isMaximizeGoal() {
		return maximizeGoal_;
	}

	/**
	 * @param maximizeGoal the maximizeGoal to set
	 */
	public void setMaximizeGoal(boolean maximizeGoal) {
		maximizeGoal_ = maximizeGoal;
	}
	
	

	/**
	 * @return the sourceVariableValuesTable
	 */
	public Map<Object,Map<Object, Integer>> getSourceVariableValuesTable() {
		return sourceVariableValuesTable_;
	}

	/**
	 * @param sourceVariableValuesTable the sourceVariableValuesTable to set
	 */
	public void setSourceVariableValuesTable(
			Map<Object,Map<Object, Integer>> sourceVariableValuesTable) {
		sourceVariableValuesTable_ = sourceVariableValuesTable;
	}

	
	
	/**
	 * @return the injectionValues
	 */
	public Map<String, Object> getInjectionValues(Object src) {
		return injectionValues_.get(src);
	}

	/**
	 * @param injectionValues the injectionValues to set
	 */
	public void setInjectionValues(Object src,Map<String, Object> injectionValues) {
		injectionValues_.put(src,injectionValues);
	}

	public void inject(RefreshCore core) {
		core.setSetsToMap(sourceItems_, targetItems_);

		for (Object src : requiresMap_.keySet()) {
			List requires = requiresMap_.get(src);
			if (requires != null && requires.size() > 0) {
				for (Object req : requires) {
					core.addRequiresMappingConstraint(src, req);
				}
			}
		}

		for (Object src : excludesMap_.keySet()) {
			List requires = excludesMap_.get(src);
			if (requires != null && requires.size() > 0) {
				for (Object req : requires) {
					core.addExcludesMappingConstraint(src, req);
				}
			}
		}

		for (Object src : selectMap_.keySet()) {
			List requires = selectMap_.get(src);
			if (requires != null && requires.size() > 0) {
				Cardinality card = (Cardinality) requires.get(0);
				requires.remove(0);
				core.addSelectMappingConstraint(src, requires, card.getMin(),
						card.getMax());
			}
		}

		for (Object src : sourceMappedInstancesCountMap_.keySet()) {
			Cardinality card = sourceMappedInstancesCountMap_.get(src);
			if (card != null) {
				core.addSourceMappedCardinalityConstraint(src, card.getMin(),
						card.getMax());
			}
		}

		for (Object src : targetMappedInstancesCountMap_.keySet()) {
			Cardinality card = targetMappedInstancesCountMap_.get(src);
			if (card != null) {
				core.addTargetMappedSourcesCardinalityConstraint(src, card
						.getMin(), card.getMax());
			}
		}

		for (Object src : sourceFeasibilityConstraintsMap_.keySet()) {
			List<Constraint> cons = sourceFeasibilityConstraintsMap_.get(src);
			if (cons != null) {
				for (Constraint con : cons) {
					core.addSourceMappingConstraint(src, (BinaryExpression) con
							.getExpression());
				}
			}
		}

		for (Object src : feasibleTargetsMap_.keySet()) {
			List valid = feasibleTargetsMap_.get(src);
			if (valid != null) {
				core.setValidTargets(src, valid);
			}
		}
		
		for (Object src : sourceVariableValuesTable_.keySet()){
			core.setSourceVariableValues(src, sourceVariableValuesTable_.get(src));
		}
		
		if(goalFunction_ != null){
			core.setOptimizationFunction(goalFunction_);
			core.setMaximizeOptimizationFunction(maximizeGoal_);
		}
	}
}
